import forgotPasswordPhoneSendCodeApi from '@/api/user/forgotPasswordPhoneSendCodeApi'
import loginPhoneSendCodeAPi from '@/api/user/loginPhoneSendCodeAPi'
import regEmailSendCodeApi from '@/api/user/regEmailSendCodeApi'
import regPhoneSendCodeApi from '@/api/user/regPhoneSendCodeApi'
import userCenterBindEmailSendCodeAPi from '@/api/userCenter/userCenterBindEmailSendCodeAPi'
import userCenterBindPhoneSendCodeAPi from '@/api/userCenter/userCenterBindPhoneSendCodeAPi'
import userCenterUpdateEmailSendCodeApi from '@/api/userCenter/userCenterUpdateEmailSendCodeApi'
import userCenterUpdatePhoneSendCodeApi from '@/api/userCenter/userCenterUpdatePhoneSendCodeApi'
import { getAppNav } from '@/App'
import LocalStorageKey from '@/constant/LocalStorageKey'
import IResVO from '@/model/vo/common/IResVO'
import { AxiosResponse } from 'axios'
import { SHA256 } from 'crypto-js'
import JsEncrypt from 'jsencrypt'
import { Dispatch, MutableRefObject, SetStateAction } from 'react'
import { randomString, ToastError, ToastSuccess } from './CommonUtil'
import { validate } from './Validator'

const sendCodeDisableNumber = 60

// 1 暂无 2 登录/注册手机验证码 3 手机邮箱注册验证码 4 修改邮箱时邮箱验证码 5 忘记密码时手机验证码 6 修改手机验证码 7 绑定邮箱验证码 8 绑定手机验证码
const sendCodeTypeArr = <const>[2, 3, 4, 5, 6, 7, 8]
export type SendCodeType = typeof sendCodeTypeArr[number]

// 发送验证码
export function sendCode(
  value: string,
  setCodeText: Dispatch<SetStateAction<string>>,
  timer: MutableRefObject<NodeJS.Timer | undefined>,
  clearTimer: () => void,
  type: SendCodeType
) {
  setCodeText(sendCodeDisableNumber + 's')

  if (type === 2) {
    doSendCodeApi(
      loginPhoneSendCodeAPi({ phone: value }),
      timer,
      clearTimer,
      sendCodeDisableNumber,
      setCodeText
    )
  } else if (type === 3) {
    if (validate.email.validate(value)) {
      doSendCodeApi(
        regEmailSendCodeApi({ email: value }),
        timer,
        clearTimer,
        sendCodeDisableNumber,
        setCodeText
      )
    } else if (validate.phone.validate(value)) {
      doSendCodeApi(
        regPhoneSendCodeApi({ phone: value }),
        timer,
        clearTimer,
        sendCodeDisableNumber,
        setCodeText
      )
    } else {
      ToastError('暂不支持此账号类型：' + value)
    }
  } else if (type === 4) {
    doSendCodeApi(
      userCenterUpdateEmailSendCodeApi({ email: value }),
      timer,
      clearTimer,
      sendCodeDisableNumber,
      setCodeText
    )
  } else if (type === 5) {
    doSendCodeApi(
      forgotPasswordPhoneSendCodeApi({ phone: value }),
      timer,
      clearTimer,
      sendCodeDisableNumber,
      setCodeText
    )
  } else if (type === 6) {
    doSendCodeApi(
      userCenterUpdatePhoneSendCodeApi({ phone: value }),
      timer,
      clearTimer,
      sendCodeDisableNumber,
      setCodeText
    )
  } else if (type === 7) {
    doSendCodeApi(
      userCenterBindEmailSendCodeAPi({ email: value }),
      timer,
      clearTimer,
      sendCodeDisableNumber,
      setCodeText
    )
  } else if (type === 8) {
    doSendCodeApi(
      userCenterBindPhoneSendCodeAPi({ phone: value }),
      timer,
      clearTimer,
      sendCodeDisableNumber,
      setCodeText
    )
  }
}

// 统一的，发送验证码方法
function doSendCodeApi(
  api: Promise<AxiosResponse<IResVO<string>, any>>,
  timer: MutableRefObject<NodeJS.Timer | undefined>,
  clearTimer: () => void,
  number: number,
  setCodeText: Dispatch<SetStateAction<string>>
) {
  api
    .then(({ data }) => {
      ToastSuccess(data.msg)
      timer.current = setInterval(() => {
        number -= 1
        if (number <= 0) {
          clearTimer()
          setCodeText('获取验证码')
          return
        }
        setCodeText(number + 's')
      }, 1000)
    })
    .catch((e) => {
      setCodeText('获取验证码')
    })
}

// 统一的 password加密
export function passwordRSAEncrypt(
  password: string | undefined,
  rsaPublicKey: string,
  date: Date = new Date()
) {
  if (!password) {
    return undefined
  }
  return RSAEncryptPro(
    SHA256(SHA256(password).toString()).toString(),
    rsaPublicKey,
    date
  )
}

// 非对称加密：增强版，word 加入时间戳
export function RSAEncryptPro(
  word: string | undefined,
  rsaPublicKey: string,
  date: Date = new Date()
) {
  if (!word) {
    return undefined
  }
  const timestamp = ';' + date.setMinutes(date.getMinutes() + 1) // 时间戳
  return RSAEncrypt(word + timestamp, rsaPublicKey) as string // 加入时间戳，进行非对称加密
}

// 非对称加密
export function RSAEncrypt(word: string | undefined, rsaPublicKey: string) {
  if (!word) {
    return undefined
  }
  const jse = new JsEncrypt()
  jse.setPublicKey(rsaPublicKey) // 设置公钥
  return jse.encrypt(word)
}

// 登出
export function logout() {
  localStorage.removeItem(LocalStorageKey.JWT)
  getAppNav()('/')
}

// 随机昵称
export function randomNickname() {
  return '用户昵称' + randomString(6).toUpperCase()
}
